package com.soft.zosagent.util;

import com.ibm.jzos.Exec;
import com.ibm.jzos.RcException;
import com.ibm.jzos.ZFile;
import com.ibm.jzos.ZUtil;
import com.soft.zosagent.common.Constant;
import com.soft.zosagent.pojo.JobInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.*;

public class ZosUtil {
    public static final String JOB_STATUS_CMD = "jobStatus";
    public static final String JOB_OUTPUT_CMD = "jobOutput";
    public static final String JOB_CANCEL_CMD = "cancelJob";
    public static final String JOB_GETNAME = "getJobName";
    public static final String JOB_GETJOBINFO_CMD = "getJobInfo";
    private static Logger logger = Logger.getLogger(ZosUtil.class);

    public static String getJobNameByJobId(String jobId) throws IOException{
        Exec exec = new Exec(getJobNameByJobidCommand(jobId), getEnvironment());
        exec.run();

        String line = exec.readLine();
        if (line == null) throw new IOException("No output from jobStatus child process");

        // close the stream which is connected
        // to the stdin input of the external process
        BufferedWriter wdr = exec.getStdinWriter();
        wdr.close();

        // slurp other output
        while (exec.readLine() != null) {};

        int rc = exec.getReturnCode();
        if (rc != 0) {
            throw new RcException("REXX '"+JOB_GETNAME+"' process failed: " + line, rc);
        }

        return line;
    }

    protected static String getJobNameByJobidCommand(String jobId) {
        String cmdPath = System.getenv("AGENT_SCRIPT_PATH");
        if (cmdPath!=null && cmdPath.length() > 0 && !cmdPath.endsWith("/")) {
            cmdPath = cmdPath + "/";
        }else{
            cmdPath="";
        }

        cmdPath = cmdPath + JOB_GETNAME
                + " "
                + jobId
                + " ";
        return cmdPath;
    }

    protected static String[] getEnvironment() {
        Properties p = ZUtil.getEnvironment();
        p.put("_BPX_SHAREAS", "YES");
        p.put("_BPX_SPAWN_SCRIPT", "YES");

        String[] environ = new String[p.size()];
        int i = 0;

        for (Iterator<Object> iter = p.keySet().iterator(); iter.hasNext();) {
            String key = (String)iter.next();
            environ[i++] = key + "=" + p.getProperty(key);
        }

        return environ;
    }

    public static String getStatus(String jobN, String jobId) throws IOException {
        Exec exec = new Exec(getStatusCommand(jobN,jobId), getEnvironment());
        exec.run();

        String line = exec.readLine();
        if (line == null) throw new IOException("No output from jobStatus child process");

        // close the stream which is connected
        // to the stdin input of the external process
        BufferedWriter wdr = exec.getStdinWriter();
        wdr.close();

        // slurp other output
        while (exec.readLine() != null) {};

        int rc = exec.getReturnCode();
        if (rc != 0) {
            throw new RcException("REXX 'jobStatus' process failed: " + line, rc);
        }

        StringTokenizer tok = new StringTokenizer(line);
        if (tok.countTokens() < 3 ) {
            throw new IOException("Invalid output from jobStatus child process: " + line);
        }

        String next = tok.nextToken();

        // skip over message id
        if (next.startsWith("IKJ")) {
            next = tok.nextToken();
        }

        if (!next.equalsIgnoreCase("JOB")) {
            throw new IOException("Invalid output from jobStatus child process: " + line);
        }

        // skip jobname(jobid)
        tok.nextToken();
        String answer = "";

        // concat remaining words
        while (tok.hasMoreTokens()) {
            answer += tok.nextToken();

            if (tok.hasMoreTokens()) {
                answer += " ";
            }
        }
        return answer;
    }

    protected static String getStatusCommand(String jobName,String jobId) {
        //String cmdPath = System.getProperty("jzos.script.path", "");
        String cmdPath = System.getenv("AGENT_SCRIPT_PATH");
        if (cmdPath!=null && cmdPath.length() > 0 && !cmdPath.endsWith("/")) {
            cmdPath = cmdPath + "/";
        }else{
            cmdPath="";
        }

        cmdPath = cmdPath + JOB_STATUS_CMD
                + " "
                + jobName
                + " ";

        if (StringUtils.isNotBlank(jobId) ) {
            cmdPath = cmdPath + jobId;
        }

        return cmdPath;
    }

    public static List<String> readPdsMemberFile(String fileName) {
        List<String> lines = new ArrayList<>();
        if(!fileName.matches("[a-zA-z\\.]+\\([a-zA-Z][a-zA-z\\@\\#0-9]+\\)")){
            logger.warn("filename:"+fileName+",doesn't macth rule: "+"[a-zA-z\\.]+\\([a-zA-Z][a-zA-z\\@\\#0-9]+\\)");
            return lines;
        }

        ZFile dsnFile = null;

        try {

            // open the dataset
            dsnFile = new ZFile("//'"+fileName+"'", "rb,type=record,noseek");

            int nRead;
            byte[] recBuf = new byte[dsnFile.getLrecl()];

            while((nRead = dsnFile.read(recBuf)) != -1) {
                lines.add(new String(recBuf,"IBM935"));
            }
        }
        catch (Exception e) {
            logger.error("Unable to read " + fileName,e);
        }
        finally {
            try {
                if (dsnFile != null) {
                    dsnFile.close();
                }
            } catch (Exception e) {}
        }
        return lines;
    }

    public static List<String> writeJobOutput(String jobName,String jobId) throws IOException {
        Exec exec = new Exec(getJobOutputCommand(jobName,jobId), getEnvironment());
        exec.run();
        List<String> jobOutputLines = new ArrayList<>();
        try {
            String line;
            while ((line = exec.readLine()) != null) {
                jobOutputLines.add(line);
            }
        }
        finally {
            int rc = exec.getReturnCode();
            if (rc != 0) {
                throw new RcException("REXX 'jobOutput' process failed", rc);
            }
        }
        return jobOutputLines;
    }

    protected static String getJobOutputCommand(String jobName,String jobId) {
        String cmdPath = System.getenv("AGENT_SCRIPT_PATH");
        if (cmdPath!=null && cmdPath.length() > 0 && !cmdPath.endsWith("/")) {
            cmdPath = cmdPath + "/";
        }else{
            cmdPath="";
        }

        return cmdPath + JOB_OUTPUT_CMD
                + " "
                + jobName
                + " "
                + jobId;
    }

    /**
     * 根据作业情况，设置相关信息
     * @param jobInfo
     * @param jobStatus
     */
    public static void setupJobInfoByJobStatus(JobInfo jobInfo, String jobStatus) throws Exception {
        if(jobStatus != null && jobStatus.contains("OUTPUT")){
            //表示作业已经结束
            jobInfo.setStatus(Constant.JOBSTATUS_STOPPED);

            //执行其他命令，获取作业返回的具体信息，主要是返回码

            String jobInfoStr = getJobInfoByJes2Cmd(jobInfo.getJobId());

            int ccpos = jobInfoStr.indexOf("CC=");

            int leftbracket=0;
            int rigthbracket=0;
            int endpos=0;
            //左括弧是0，右括弧大于0的时候，就是cc的全部内容
            for(int i=ccpos;i<jobInfoStr.length();i++){
                    if(jobInfoStr.charAt(i) == '('){
                        leftbracket++;

                    }else if(jobInfoStr.charAt(i) == ')'){
                        leftbracket--;
                        rigthbracket++;
                    }

                    if(leftbracket==0 && rigthbracket >0){
                        endpos = i;
                        break;
                    }
            }

            String ccStr = jobInfoStr.substring(ccpos+4,endpos);
            System.out.println(ccStr);
            String rtnType="";String rtnValue="";
            if(ccStr.contains(",")) {
                rtnType = ccStr.substring(0, ccStr.indexOf(","));
                rtnValue = ccStr.substring(ccStr.indexOf(",") + 1);
                if(rtnValue.contains("=")){
                    rtnValue = rtnValue.split("=")[1];
                }
                rtnValue = rtnValue.replace("(","");
                rtnValue = rtnValue.replace(")","");
                System.out.println(rtnType + "|" + rtnValue);
            }else{
                rtnType = ccStr;
            }
            jobInfo.setRcType(rtnType);
            jobInfo.setRcValue(rtnValue);
        }else if (jobStatus != null && jobStatus.contains("EXECUTING")){
            //表示作业仍然在运行
            jobInfo.setStatus(Constant.JOBSTATUS_EXECUTING);
        }else if (jobStatus != null && jobStatus.contains("WAITING FOR EXECUTION")){
            //表示作业仍然在运行
            jobInfo.setStatus(Constant.JOBSTATUS_WAITINGFORRUN);
        }

        else{
            //作业找不到
            jobInfo.setStatus(Constant.JOBSTATUS_NOTFOUND);
        }


    }

    public static String getJobInfoByJes2Cmd (String jobId) throws Exception{
        String cmdPath = System.getenv("AGENT_SCRIPT_PATH");
        if (cmdPath!=null && cmdPath.length() > 0 && !cmdPath.endsWith("/")) {
            cmdPath = cmdPath + "/";
        }else{
            cmdPath="";
        }
        //组装命令
        cmdPath  = cmdPath + JOB_GETJOBINFO_CMD
                + " "
                + jobId;
        Exec exec = new Exec(cmdPath, getEnvironment());
        exec.run();
        List<String> cmdOutput = new ArrayList<>();
        try {
            String line;
            while ((line = exec.readLine()) != null) {
                cmdOutput.add(line);
            }
        }
        finally {
            int rc = exec.getReturnCode();
            if (rc != 0) {
                throw new RcException("REXX 'getJobInfo' process failed,msg:"+cmdOutput, rc);
            }
        }

        return StringUtils.join(cmdOutput,"");


    }

    public static void cancelJob(String jobId) throws Exception{
        String cmdPath = System.getenv("AGENT_SCRIPT_PATH");
        if (cmdPath!=null && cmdPath.length() > 0 && !cmdPath.endsWith("/")) {
            cmdPath = cmdPath + "/";
        }else{
            cmdPath="";
        }
        //组装命令
        cmdPath  = cmdPath + JOB_CANCEL_CMD
                + " "
                + jobId;

        Exec exec = new Exec(cmdPath, getEnvironment());
        exec.run();
        List<String> cmdOutput = new ArrayList<>();
        try {
            String line;
            while ((line = exec.readLine()) != null) {
                cmdOutput.add(line);
            }
        }
        finally {
            int rc = exec.getReturnCode();
            if (rc != 0) {
                throw new RcException("REXX 'cancelJob' process failed,msg:"+cmdOutput, rc);
            }
        }



    }

    public static void main(String[] args) {
        String str = "123(fdsfdsfdsfd)xx";
        System.out.println(str.substring(str.indexOf("("),str.indexOf(")")));
    }
}
